﻿using System;
using System.Threading.Tasks;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using XfTech.SmartTms.IServices;
using XfTech.SmartTms.Entities;
using XfTech.SmartTms.ValueObjects;
using Volo.Abp.EventBus.Local;
using XfTech.SmartTms.Events;
using XfTech.SmartTms.Entities.BusinessAudit;
using Volo.Abp.Identity;
using XfTech.SmartTms.Vehicles.Dtos;
using XfTech.SmartTms.Data;

namespace XfTech.SmartTms.Vehicles
{
    /// <summary>
    /// 车辆应用接口实现类
    /// </summary>
    [Authorize] //该控制器的方法需要授权（Token）才能被访问
    public class VehicleAppService : SmartTmsAppService, IVehicleAppService
    {
        private readonly IVehicleRepository _repositoryVehicle;
        private readonly IRepository<IdentityUser> _repositoryUser;

        private readonly ILocalEventBus _localEventBus;

        private readonly OrganizationUnitManager _ouManager;  //组织部门领域服务类

        /// <summary>
        /// 构造方法进行依赖注入
        /// </summary>
        /// <param name="repositoryVehicle"></param>
        public VehicleAppService(IVehicleRepository repositoryVehicle,
                                ILocalEventBus localEventBus,
                                IRepository<IdentityUser> repositoryUser)
        {
            _repositoryVehicle = repositoryVehicle;
            _localEventBus = localEventBus;   //本地事件总线依赖注入
            _repositoryUser = repositoryUser;
        }

        /// <summary>
        /// 添加车辆
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<VehicleDto> CreateVehicleAsync([FromForm] CreateVehicleDto input)
        {
            //开发记录：
            //传入的Dto模型是被Abp框架自动验证的（验证错误的信息去哪了呢？怎么获取？？）
            //图片上传怎么做？

            //实例化一个车辆对象
            Vehicle v = new Vehicle(
                GuidGenerator.Create(), //生成主键
                input.Brand,
                input.LicensePlate,
                input.Driver,
                input.Company,
                new VehicleSize(input.Length, input.Width, input.Height), //实例化值对象
                input.Color,
                input.BuyDate,
                input.VehicleNo,
                input.InsuranceDate,
                input.AnnualCheckDate,
                input.Maintenance,
                input.VehiclePhoto,
                input.InsurancePhoto,
                DateTime.Now,   //创建时间
                CurrentUser.Id  //当前用户Id
                );

            //使用仓储接口进行持久化
            var result = await _repositoryVehicle.InsertAsync(v);

            //添加审核日志和审核明细代码（todo）
            Audit auditInfo = new Audit(GuidGenerator.Create(), result.Id, Enums.BusinessType.Vehicle, DateTime.Now, CurrentUser.Id);

            //根据当前用户Id获取它的部门领导

            //auditInfo.AddAuditLog(GuidGenerator.Create(), )


            //发送邮件(用本地事件总线）
            await _localEventBus.PublishAsync(
                    new VehicleAddedEvent   //事件类
                    {
                        VehicleId = result.Id,
                        Brand = result.Brand,
                        Company = result.Company,
                        Driver = result.Driver,
                        LicensePlate = result.LicensePlate
                    }
                );

            //返回创建的车辆（但出于效率及安全考虑，要转换成Dto再返回）
            return ObjectMapper.Map<Vehicle, VehicleDto>(result);
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<VehicleDto>> GetListAsync(
            PagedAndSortedResultRequestDto input)
        {
            //排序字段
            if (string.IsNullOrEmpty(input.Sorting))
            {
                input.Sorting = "Id";
            }

            //从仓储获取实体数据对象
            List<Vehicle> vehicles = await _repositoryVehicle.GetPagedListAsync(
                    input.SkipCount, input.MaxResultCount, input.Sorting
                );
            //获取总条数
            var totalCount = await _repositoryVehicle.CountAsync();

            //将实体数据转换成Dto
            List<VehicleDto> vehicleDtos =
                ObjectMapper.Map<List<Vehicle>, List<VehicleDto>>(vehicles);

            //返回分页结果集
            return new PagedResultDto<VehicleDto>(totalCount, vehicleDtos);
        }

        /// <summary>
        /// 根据Id获取信息
        /// </summary>
        /// <param name="vehicleId"></param>
        /// <returns></returns>
        [HttpGet("/api/vehicle/getbyId")]
        public async Task<VehicleDto> GetAsync(Guid vehicleId)
        {
            //根据Id获取车辆单表信息
            //Vehicle obj = await _repositoryVehicle.GetAsync(vehicleId);
            //return ObjectMapper.Map<Vehicle, VehicleDto>(obj);

            //根据Id获取信息,与用户表进行联查获取创建人名称
            var query = from v in await _repositoryVehicle.GetQueryableAsync()
                        join u in await _repositoryUser.GetQueryableAsync() on v.CreatorId equals u.Id
                        where v.Id == vehicleId
                        select new VehicleDto
                        {
                            Id = v.Id,
                            Brand = v.Brand,
                            AnnualCheckDate= v.AnnualCheckDate,
                            BuyDate= v.BuyDate,
                            Color= v.Color,
                            Company= v.Company,
                            Driver= v.Driver,
                            Height=v.Size.Height,
                            Length=v.Size.Length,
                            Width=v.Size.Width,
                            InsuranceDate= v.InsuranceDate,
                            InsurancePhoto= v.InsurancePhoto,
                            LicensePlate= v.LicensePlate,
                            Maintenance= v.Maintenance,
                            VehicleNo= v.VehicleNo,
                            VehiclePhoto= v.VehiclePhoto,
                            CreatorId = v.CreatorId,
                            CreationTime = v.CreationTime,
                            CreatorName = u.UserName,   //关联的创建人用户名
                        };

            return await query.SingleOrDefaultAsync();
        }
    }
}
